import javax.swing.*;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.sql.*;
import java.util.ArrayList;
import java.util.List;


class RestaurantSystem extends JFrame {
    // 修改 JDBC URL，添加 allowPublicKeyRetrieval=true 参数
    private static final String DB_URL = "jdbc:mysql://localhost:3306/restaurant?useSSL=false&serverTimezone=UTC&allowPublicKeyRetrieval=true";
    private static final String DB_USER = "root";
    private static final String DB_PASSWORD = "2394257748Yk";

    private JTabbedPane tabbedPane;
    private JPanel menuPanel, orderPanel, queryPanel;
    private List<Dish> selectedDishes = new ArrayList<>();
    private DefaultListModel<Dish> menuModel = new DefaultListModel<>();
    private DefaultListModel<Dish> selectedDishesModel = new DefaultListModel<>();
    private JList<Dish> menuList, selectedDishesList;
    private JLabel totalPriceLabel;

    public RestaurantSystem() {
        setTitle("餐厅点餐系统");
        setSize(800, 600);
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        setLocationRelativeTo(null);

        initComponents();
        loadMenuItems();

        setVisible(true);
    }

    private void initComponents() {
        tabbedPane = new JTabbedPane();

        // 初始化菜单面板
        initMenuPanel();
        // 初始化订单面板
        initOrderPanel();
        // 初始化查询面板
        initQueryPanel();

        tabbedPane.addTab("菜单管理", menuPanel);
        tabbedPane.addTab("点餐", orderPanel);
        tabbedPane.addTab("订单查询", queryPanel);

        add(tabbedPane);
    }

    private void initMenuPanel() {
        menuPanel = new JPanel(new BorderLayout());

        // 菜品列表
        menuList = new JList<>(menuModel);
        JScrollPane menuScrollPane = new JScrollPane(menuList);

        // 添加菜品表单
        JPanel addDishPanel = new JPanel(new GridLayout(4, 2));
        JTextField nameField = new JTextField();
        JTextField priceField = new JTextField();
        JTextField descriptionField = new JTextField();
        JButton addButton = new JButton("添加菜品");

        addDishPanel.add(new JLabel("菜品名称:"));
        addDishPanel.add(nameField);
        addDishPanel.add(new JLabel("价格:"));
        addDishPanel.add(priceField);
        addDishPanel.add(new JLabel("描述:"));
        addDishPanel.add(descriptionField);
        addDishPanel.add(new JLabel());
        addDishPanel.add(addButton);

        addButton.addActionListener(e -> {
            String name = nameField.getText().trim();
            if (name.isEmpty()) {
                JOptionPane.showMessageDialog(this, "菜品名称不能为空！", "错误", JOptionPane.ERROR_MESSAGE);
                return;
            }

            try {
                double price = Double.parseDouble(priceField.getText());
                if (price <= 0) {
                    throw new NumberFormatException("价格必须大于0");
                }

                String description = descriptionField.getText();

                addDish(name, price, description);
                menuModel.addElement(new Dish(name, price, description));

                nameField.setText("");
                priceField.setText("");
                descriptionField.setText("");
            } catch (NumberFormatException ex) {
                JOptionPane.showMessageDialog(this, "请输入有效的价格！", "错误", JOptionPane.ERROR_MESSAGE);
            }
        });

        menuPanel.add(menuScrollPane, BorderLayout.CENTER);
        menuPanel.add(addDishPanel, BorderLayout.SOUTH);
    }

    private void initOrderPanel() {
        orderPanel = new JPanel(new BorderLayout());

        // 分隔面板
        JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);

        // 可选菜品列表
        menuList = new JList<>(menuModel);
        menuList.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
        JScrollPane availableScrollPane = new JScrollPane(menuList);

        // 已选菜品列表
        selectedDishesList = new JList<>(selectedDishesModel);
        JScrollPane selectedScrollPane = new JScrollPane(selectedDishesList);

        splitPane.setLeftComponent(availableScrollPane);
        splitPane.setRightComponent(selectedScrollPane);
        splitPane.setDividerLocation(400);

        // 按钮面板
        JPanel buttonPanel = new JPanel();
        JButton addToOrderButton = new JButton("添加到订单");
        JButton removeFromOrderButton = new JButton("从订单移除");
        JButton placeOrderButton = new JButton("提交订单");
        totalPriceLabel = new JLabel("总价: ¥0.00");

        buttonPanel.add(addToOrderButton);
        buttonPanel.add(removeFromOrderButton);
        buttonPanel.add(placeOrderButton);
        buttonPanel.add(totalPriceLabel);

        addToOrderButton.addActionListener(e -> {
            List<Dish> selected = menuList.getSelectedValuesList();
            for (Dish dish : selected) {
                if (!selectedDishes.contains(dish)) {
                    selectedDishes.add(dish);
                    selectedDishesModel.addElement(dish);
                }
            }
            updateTotalPrice();
        });

        removeFromOrderButton.addActionListener(e -> {
            List<Dish> selected = selectedDishesList.getSelectedValuesList();
            for (Dish dish : selected) {
                selectedDishes.remove(dish);
                selectedDishesModel.removeElement(dish);
            }
            updateTotalPrice();
        });

        placeOrderButton.addActionListener(e -> {
            if (selectedDishes.isEmpty()) {
                JOptionPane.showMessageDialog(this, "请先选择菜品！", "提示", JOptionPane.INFORMATION_MESSAGE);
                return;
            }

            double totalPrice = calculateTotalPrice();
            int confirm = JOptionPane.showConfirmDialog(this,
                    "确认提交订单？总价: ¥" + totalPrice,
                    "确认订单",
                    JOptionPane.YES_NO_OPTION);

            if (confirm == JOptionPane.YES_OPTION) {
                int orderId = placeOrder(selectedDishes, totalPrice);
                if (orderId > 0) {
                    selectedDishes.clear();
                    selectedDishesModel.clear();
                    updateTotalPrice();
                    JOptionPane.showMessageDialog(this, "订单提交成功！订单ID: " + orderId, "成功", JOptionPane.INFORMATION_MESSAGE);
                }
            }
        });

        orderPanel.add(splitPane, BorderLayout.CENTER);
        orderPanel.add(buttonPanel, BorderLayout.SOUTH);
    }

    private void initQueryPanel() {
        queryPanel = new JPanel(new BorderLayout());

        // 查询表单
        JPanel queryFormPanel = new JPanel(new FlowLayout());
        JTextField orderIdField = new JTextField(10);
        JButton queryButton = new JButton("查询订单");
        JButton queryAllButton = new JButton("查询所有订单");

        queryFormPanel.add(new JLabel("订单ID:"));
        queryFormPanel.add(orderIdField);
        queryFormPanel.add(queryButton);
        queryFormPanel.add(queryAllButton);

        // 订单详情表格
        String[] columnNames = {"订单ID", "菜品名称", "价格", "下单时间"};
        DefaultTableModel tableModel = new DefaultTableModel(columnNames, 0);
        JTable orderTable = new JTable(tableModel);
        JScrollPane tableScrollPane = new JScrollPane(orderTable);

        queryButton.addActionListener(e -> {
            String orderId = orderIdField.getText();
            if (orderId.isEmpty()) {
                JOptionPane.showMessageDialog(this, "请输入订单ID！", "提示", JOptionPane.INFORMATION_MESSAGE);
                return;
            }

            try {
                int id = Integer.parseInt(orderId);
                queryOrder(tableModel, id);
            } catch (NumberFormatException ex) {
                JOptionPane.showMessageDialog(this, "请输入有效的订单ID！", "错误", JOptionPane.ERROR_MESSAGE);
            }
        });

        queryAllButton.addActionListener(e -> queryOrder(tableModel, -1));

        queryPanel.add(queryFormPanel, BorderLayout.NORTH);
        queryPanel.add(tableScrollPane, BorderLayout.CENTER);
    }

    private void loadMenuItems() {
        menuModel.clear();
        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
             Statement stmt = conn.createStatement();
             ResultSet rs = stmt.executeQuery("SELECT * FROM dishes")) {

            while (rs.next()) {
                String name = rs.getString("name");
                double price = rs.getDouble("price");
                String description = rs.getString("description");
                menuModel.addElement(new Dish(name, price, description));
            }
        } catch (SQLException ex) {
            ex.printStackTrace();
            JOptionPane.showMessageDialog(this, "加载菜单失败: " + ex.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
        }
    }

    private void addDish(String name, double price, String description) {
        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD);
             PreparedStatement pstmt = conn.prepareStatement(
                     "INSERT INTO dishes (name, price, description) VALUES (?, ?, ?)")) {

            pstmt.setString(1, name);
            pstmt.setDouble(2, price);
            pstmt.setString(3, description);
            pstmt.executeUpdate();
        } catch (SQLException ex) {
            ex.printStackTrace();
            JOptionPane.showMessageDialog(this, "添加菜品失败: " + ex.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
        }
    }

    private int placeOrder(List<Dish> dishes, double totalPrice) {
        int orderId = -1;
        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD)) {
            conn.setAutoCommit(false);

            try (PreparedStatement orderStmt = conn.prepareStatement(
                    "INSERT INTO orders (total_price, order_time) VALUES (?, NOW())",
                    Statement.RETURN_GENERATED_KEYS)) {

                orderStmt.setDouble(1, totalPrice);
                orderStmt.executeUpdate();

                ResultSet generatedKeys = orderStmt.getGeneratedKeys();
                if (generatedKeys.next()) {
                    orderId = generatedKeys.getInt(1);

                    for (Dish dish : dishes) {
                        try (PreparedStatement itemStmt = conn.prepareStatement(
                                "INSERT INTO order_items (order_id, dish_id) VALUES (?, ?)")) {

                            // 获取菜品ID
                            try (PreparedStatement dishStmt = conn.prepareStatement(
                                    "SELECT id FROM dishes WHERE name = ? AND price = ?")) {

                                dishStmt.setString(1, dish.getName());
                                dishStmt.setDouble(2, dish.getPrice());
                                ResultSet dishRs = dishStmt.executeQuery();

                                if (dishRs.next()) {
                                    int dishId = dishRs.getInt("id");
                                    itemStmt.setInt(1, orderId);
                                    itemStmt.setInt(2, dishId);
                                    itemStmt.executeUpdate();
                                }
                            }
                        }
                    }
                }

                conn.commit();
            } catch (SQLException ex) {
                conn.rollback();
                throw ex;
            } finally {
                conn.setAutoCommit(true);
            }
        } catch (SQLException ex) {
            ex.printStackTrace();
            JOptionPane.showMessageDialog(this, "提交订单失败: " + ex.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
        }
        return orderId;
    }

    private void queryOrder(DefaultTableModel tableModel, int orderId) {
        tableModel.setRowCount(0);

        try (Connection conn = DriverManager.getConnection(DB_URL, DB_USER, DB_PASSWORD)) {
            String sql;
            PreparedStatement pstmt;

            if (orderId > 0) {
                sql = "SELECT o.id, d.name, d.price, o.order_time " +
                        "FROM orders o " +
                        "JOIN order_items oi ON o.id = oi.order_id " +
                        "JOIN dishes d ON oi.dish_id = d.id " +
                        "WHERE o.id = ?";
                pstmt = conn.prepareStatement(sql);
                pstmt.setInt(1, orderId);
            } else {
                sql = "SELECT o.id, d.name, d.price, o.order_time " +
                        "FROM orders o " +
                        "JOIN order_items oi ON o.id = oi.order_id " +
                        "JOIN dishes d ON oi.dish_id = d.id " +
                        "ORDER BY o.order_time DESC";
                pstmt = conn.prepareStatement(sql);
            }

            ResultSet rs = pstmt.executeQuery();

            while (rs.next()) {
                int id = rs.getInt("id");
                String name = rs.getString("name");
                double price = rs.getDouble("price");
                String orderTime = rs.getString("order_time");

                tableModel.addRow(new Object[]{id, name, price, orderTime});
            }

            if (tableModel.getRowCount() == 0) {
                JOptionPane.showMessageDialog(this,
                        orderId > 0 ? "未找到该订单！" : "暂无订单记录！",
                        "提示", JOptionPane.INFORMATION_MESSAGE);
            }
        } catch (SQLException ex) {
            ex.printStackTrace();
            JOptionPane.showMessageDialog(this, "查询订单失败: " + ex.getMessage(), "错误", JOptionPane.ERROR_MESSAGE);
        }
    }

    private double calculateTotalPrice() {
        double total = 0;
        for (Dish dish : selectedDishes) {
            total += dish.getPrice();
        }
        return total;
    }

    private void updateTotalPrice() {
        double total = calculateTotalPrice();
        totalPriceLabel.setText("总价: ¥" + String.format("%.2f", total));
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(RestaurantSystem::new);
    }
}

class Dish {
    private String name;
    private double price;
    private String description;

    public Dish(String name, double price, String description) {
        this.name = name;
        this.price = price;
        this.description = description;
    }

    public String getName() {
        return name;
    }

    public double getPrice() {
        return price;
    }

    public String getDescription() {
        return description;
    }

    @Override
    public String toString() {
        return name + " - ¥" + String.format("%.2f", price);
    }

    @Override
    public boolean equals(Object obj) {
        if (this == obj) return true;
        if (obj == null || getClass() != obj.getClass()) return false;
        Dish dish = (Dish) obj;
        return Double.compare(dish.price, price) == 0 &&
                name.equals(dish.name);
    }

    @Override
    public int hashCode() {
        return java.util.Objects.hash(name, price);
    }
}